package controllers;

import java.util.List;

import com.google.gson.JsonObject;

import models.Entities;
import models.IdeaDeveloper;
import models.Log;
import models.Organization;
import models.OrganizationLead;
import models.Picture;
import models.Request;
import models.Tag;
import models.Topic;

import org.apache.commons.mail.EmailException;
import play.mvc.Controller;
import play.mvc.With;

/**
 * @author KimO
 */
@With(Secure.class)
public class UserProfile extends Controller {

	/**
	 *  renders the users profile according to the the user who is
	 * logged in already
	 * 
	 * @author KimO
	 */
	public static void SelfUserProfile() {

		IdeaDeveloper user = IdeaDeveloper.find("username = ?",
				Security.connected()).first();
		boolean isOrgLead = OrganizationLead.find("ideaDeveloper", user)
				.first() != null;
		render(isOrgLead);
	}

	/**
	 *  renders the profile the logged in user want to see
	 * 
	 * @author KimO
	 * @param userId
	 *            the id of the user who owns the page
	 */
	public static void OtherUserProfile(long userId) {
		if (userId == Security.userid()) {
			SelfUserProfile();
		} else {
			render(userId);
		}
	}

	/**
	 *  loads the current user info and send then as a java script
	 * object to the view
	 * 
	 * @author KimO
	 */
	public static void loadUserInfo() {
		IdeaDeveloper currentIdeaDeveloper = IdeaDeveloper.find("id=?",
				Security.userid()).first();
		JsonObject loadUser = new JsonObject();
		loadUser.addProperty("fullName", currentIdeaDeveloper.fullName);
		loadUser.addProperty("eMail", currentIdeaDeveloper.eMail);
		loadUser.addProperty("dateOfBirth", currentIdeaDeveloper.dateOfBirth);
		loadUser.addProperty("address", currentIdeaDeveloper.address);
		loadUser.addProperty("numberOfIdeasPosted",
				currentIdeaDeveloper.createdIdeas.size());
		loadUser.addProperty("numberOfComments",
				currentIdeaDeveloper.createdComments.size());
		loadUser.addProperty("mobileNumber", currentIdeaDeveloper.mobileNumber);
		renderJSON(loadUser.toString());
	}

	/**
	 *  loads the user info and send then as a java script object to
	 * the view
	 * 
	 * @author KimO
	 * @param userId
	 *            the id of the user that owns the page
	 */
	public static void loadHisUserInfo(long userId) {
		IdeaDeveloper currentIdeaDeveloper = IdeaDeveloper.find("id=?", userId)
				.first();
		JsonObject loadInformation = new JsonObject();
		loadInformation.addProperty("fullName", currentIdeaDeveloper.fullName);
		loadInformation.addProperty("eMail", currentIdeaDeveloper.eMail);
		loadInformation.addProperty("dateOfBirth",
				currentIdeaDeveloper.dateOfBirth);
		loadInformation.addProperty("address", currentIdeaDeveloper.address);
		loadInformation.addProperty("numberOfIdeasPosted",
				currentIdeaDeveloper.createdIdeas.size());
		loadInformation.addProperty("numberOfComments",
				currentIdeaDeveloper.createdComments.size());
		loadInformation.addProperty("mobileNumber",
				currentIdeaDeveloper.mobileNumber);
		renderJSON(loadInformation.toString());
	}

	/**
	 *  splits the requests to be organizer and put them all in 1
	 * string in order to be read by the view ,,, to split inside same requests
	 * and && to split different requests
	 * 
	 * @author KimO
	 * 
	 * @param currentUser
	 *            the user who we check he has requests or not
	 */
	public static void loadRequests() {

		try {
			IdeaDeveloper ideadev = (IdeaDeveloper) IdeaDeveloper
					.find("username = ?", Security.connected()).fetch().get(0);

			JsonObject loadRequests = new JsonObject();

			// json.addProperty("result", "sizeNotEqualZero");

			String listOfRequests = "";
			for (Request request : ideadev.requests) {

				if ((request.status.equalsIgnoreCase("new"))) {

					// Type = "JoinOrgFromDevToOrg" || "JoinOrgFromOrgToDev"
					// ||"JoinIdeaDeveloper"||"FriendRequest

					if (request.type == "JoinOrgFromOrgToDev") {
						listOfRequests += request.org.name + ",,,"
								+ "You have a request to join organization "
								+ request.org.name + ",,," + request.id + "AAA";
					}
					if (request.type == "JoinIdeaDeveloper") {

						if (request.org != null) {
							listOfRequests += request.org.name
									+ ",,,"
									+ "You have a request to be a leader for organization "
									+ request.org.name + ",,," + request.id
									+ "AAA";
						}
						if (request.ent != null) {
							listOfRequests += request.ent.name
									+ ",,,"
									+ "You have a request to be organizer for entity "
									+ request.ent.name + " in organization "
									+ request.ent.liesIn.name + ",,,"
									+ request.id + "AAA";
						}
					}
					if (request.type == "FriendRequest") {
						listOfRequests += request.inviterName + ",,,"
								+ request.type + ",,," + request.id + "AAA";

					}
					if (request.type == "TopicManager") {
						listOfRequests += request.topic.title
								+ ",,,"
								+ "You have a request to be organizer on topic "
								+ request.topic.title + ",,," + request.id
								+ "AAA";
					}

					loadRequests.addProperty("result", "da5al el if !");
				}
				loadRequests.addProperty("list", listOfRequests);
			}
			if (listOfRequests.equals("")) {
				loadRequests.addProperty("result", "sizeEqualZero");

				// TEST
				// listOfRequests += ideadev.username + ",,," + "request.body"
				// + ",,," + 1;
				// listOfRequests += "AAA";
				// listOfRequests += ideadev.username + "2,,," + "request.body2"
				// + ",,," + 2;
				loadRequests.addProperty("list", listOfRequests);
				// TEST
			}
			renderJSON(loadRequests.toString());

		} catch (Exception e) {
			JsonObject json = new JsonObject();
			json.addProperty("result", "Exception");
			renderJSON(json.toString());
		}
	}

	/**
	 *  is used to save the users reply on the request to be
	 * organizer
	 * 
	 * @author KimO
	 * 
	 * @param decision
	 *            the decision of the user either to accept the invitation or to
	 *            reject it
	 * @param requestId
	 *            the id of the request
	 */
	public static void saveDecisionRequest(Boolean decision, long requestId) {
		JsonObject replyRequest = new JsonObject();
		replyRequest.addProperty("dec", decision);
		replyRequest.addProperty("dec2", requestId);
		Request request = Request.findById(requestId);
		if (decision) {
			request.Accept();
			replyRequest.addProperty("result2", "Request accepted!");

		} else {
			request.delete2();
			replyRequest.addProperty("result2", "Request rejected!");

		}
		replyRequest.addProperty("result", "done");
		String temp = (decision) ? "accepted" : "rejected";
		Log log = new Log("^ has " + temp + " a request");
		log.ids = Security.userid() + "";
		log.types = "developer";
		log.save();

		renderJSON(replyRequest.toString());
	}

	/**
	 *  is used to send an email to an unregistered user to invite
	 * him to the application after checking that he is not a registered user
	 * 
	 * @author KimO
	 * 
	 * @param eMail
	 *            the email of the person who will be invited
	 * @throws EmailException
	 *             to work :D
	 */
	public static void invitationSending(String eMail) {
		IdeaDeveloper ideaDev = (IdeaDeveloper) IdeaDeveloper
				.find("username = ?", Security.connected()).fetch().get(0);
		IdeaDeveloper.sendInvitationMail(ideaDev.fullName, eMail);
		JsonObject invitation = new JsonObject();
		invitation.addProperty("res", "done");

		Log log = new Log("^ has invited" + eMail + " to join the application");
		log.ids = Security.userid() + "";
		log.types = "developer";
		log.save();

		renderJSON(invitation);
	}

	/**
	 *  load user information ( address, theme, email, and image)
	 * 
	 * @author KimO
	 */
	public static void editUserInfo() {
		JsonObject editInfo = new JsonObject();

		try {
			IdeaDeveloper ideadev = (IdeaDeveloper) IdeaDeveloper.find(
					"username = ?", Security.connected()).first();
			editInfo.addProperty("username", ideadev.username);
			editInfo.addProperty("address", ideadev.address);
			editInfo.addProperty("mobile", ideadev.mobileNumber);
			editInfo.addProperty("email", ideadev.eMail);
			renderJSON(editInfo.toString());
		} catch (Exception e) {
			renderJSON("Error");
		}
	}

	/**
	 *  saves the edited info in the idea developer table
	 * 
	 * @author KimO
	 * 
	 * @param newAddress
	 *            the new address that will replace the old address
	 * @param newTheme
	 *            the new theme chosen
	 * @param newImagePath
	 *            the new profile image path
	 */
	public static void saveUserInfoEdited(String newAddress, int mobileNumber,
			String eMail) {
		String res = IdeaDeveloper.editUserInformation(Security.connected(),
				Security.connected(), newAddress, mobileNumber, eMail);
		JsonObject saveInfo = new JsonObject();
		saveInfo.addProperty("done", res);
		Log log = new Log("^ has edited his own user information");
		log.ids = Security.userid() + "";
		log.types = "developer";
		log.save();

		renderJSON(saveInfo.toString());
	}

	/**
	 * adding image to the HTML page
	 */
	public static void getPicture() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		Picture picture = Picture.findById(ideaDeveloper.profilePicture.id);
		response.setContentTypeIfNotSet(picture.image.type());
		renderBinary(picture.image.get());
	}

	// organization , entity , topic , tag
	/**
	 * Rendering the list of organization unfollowed by the connected idea
	 * developer
	 * 
	 * @author KimO
	 */
	public static void getUnfollowedOrganizations() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		List<Organization> organizationUnfollowed = ideaDeveloper.unfollowedOrg;
		String unfollowedOrg = "";
		for (int i = 0; i < organizationUnfollowed.size(); i++) {
			unfollowedOrg += organizationUnfollowed.get(i).id + ",";
			unfollowedOrg += organizationUnfollowed.get(i).name + "&&";
		}
		if (unfollowedOrg.equals("")) {
			unfollowedOrg = "^";
		}
		JsonObject unfollowedOrganizationList = new JsonObject();
		unfollowedOrganizationList.addProperty("result", unfollowedOrg);
		renderJSON(unfollowedOrganizationList.toString());
	}

	/**
	 * Rendering the list of entities unfollowed by the connected idea developer
	 * 
	 * @author KimO
	 */
	public static void getUnfollowedEntities() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		List<Entities> entitiesUnfollowed = ideaDeveloper.unfollowedEnt;
		String unfollowedEnt = "";
		for (int i = 0; i < entitiesUnfollowed.size(); i++) {
			unfollowedEnt += entitiesUnfollowed.get(i).id + ",";
			unfollowedEnt += entitiesUnfollowed.get(i).name + "&&";
		}
		if (unfollowedEnt.equals("")) {
			unfollowedEnt = "^";
		}
		JsonObject entitiesList = new JsonObject();
		entitiesList.addProperty("result", unfollowedEnt);
		renderJSON(entitiesList.toString());
	}

	/**
	 * Rendering the list of topic unfollowed by the connected idea developer
	 * 
	 * @author KimO
	 */
	public static void getUnfollowedTopics() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		List<Topic> topicUnfollowed = ideaDeveloper.unfollowedTop;
		String unfollowedTop = "";
		for (int i = 0; i < topicUnfollowed.size(); i++) {
			unfollowedTop += topicUnfollowed.get(i).id + ",";
			unfollowedTop += topicUnfollowed.get(i).title + "&&";
		}
		if (unfollowedTop.equals("")) {
			unfollowedTop = "^";
		}
		JsonObject topicsList = new JsonObject();
		topicsList.addProperty("result", unfollowedTop);
		renderJSON(topicsList.toString());
	}

	/**
	 * Rendering the list of tag unfollowed by the connected idea developer
	 * 
	 * @author KimO
	 */
	public static void getUnfollowedTags() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		List<Tag> tagsUnfollowed = ideaDeveloper.unfollowedTag;
		String unfollowedTag = "";
		for (int i = 0; i < tagsUnfollowed.size(); i++) {
			unfollowedTag += tagsUnfollowed.get(i).id + ",";
			unfollowedTag += tagsUnfollowed.get(i).name + "&&";
		}
		if (unfollowedTag.equals("")) {
			unfollowedTag = "^";
		}
		JsonObject tagsList = new JsonObject();
		tagsList.addProperty("result", unfollowedTag);
		renderJSON(tagsList.toString());
	}

	/**
	 * Rendering the list of organization followed by the connected idea
	 * developer
	 * 
	 * @author KimO
	 */
	public static void getFollowedOrganizations() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		List<Organization> organizationFollowed = ideaDeveloper.followedOrg;
		String followedOrg = "";
		for (int i = 0; i < organizationFollowed.size(); i++) {
			followedOrg += organizationFollowed.get(i).id + ",";
			followedOrg += organizationFollowed.get(i).name + "&&";
		}
		if (followedOrg.equals("")) {
			followedOrg = "^";
		}
		JsonObject followedOrganizationList = new JsonObject();
		followedOrganizationList.addProperty("result", followedOrg);
		renderJSON(followedOrganizationList.toString());
	}

	/**
	 * Rendering the list of entities followed by the connected idea developer
	 * 
	 * @author KimO
	 */
	public static void getFollowedEntities() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		List<Entities> entitiesFollowed = ideaDeveloper.followedEnt;
		String followedEnt = "";
		for (int i = 0; i < entitiesFollowed.size(); i++) {
			followedEnt += entitiesFollowed.get(i).id + ",";
			followedEnt += entitiesFollowed.get(i).name + "&&";
		}
		if (followedEnt.equals("")) {
			followedEnt = "^";
		}
		JsonObject entitiesList = new JsonObject();
		entitiesList.addProperty("result", followedEnt);
		renderJSON(entitiesList.toString());
	}

	/**
	 * Rendering the list of topic followed by the connected idea developer
	 * 
	 * @author KimO
	 */
	public static void getFollowedTopics() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		List<Topic> topicFollowed = ideaDeveloper.followedTop;
		String followedTop = "";
		for (int i = 0; i < topicFollowed.size(); i++) {
			followedTop += topicFollowed.get(i).id + ",";
			followedTop += topicFollowed.get(i).title + "&&";
		}
		if (followedTop.equals("")) {
			followedTop = "^";
		}
		JsonObject topicsList = new JsonObject();
		topicsList.addProperty("result", followedTop);
		renderJSON(topicsList.toString());
	}

	/**
	 * Rendering the list of tag followed by the connected idea developer
	 * 
	 * @author KimO
	 */
	public static void getFollowedTags() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());
		List<Tag> tagsFollowed = ideaDeveloper.followedTag;
		String followedTag = "";
		for (int i = 0; i < tagsFollowed.size(); i++) {
			followedTag += tagsFollowed.get(i).id + ",";
			followedTag += tagsFollowed.get(i).name + "&&";
		}
		if (followedTag.equals("")) {
			followedTag = "^";
		}
		JsonObject tagsList = new JsonObject();
		tagsList.addProperty("result", followedTag);
		renderJSON(tagsList.toString());
	}

	/**
	 * Sets the follow/unfollow to something
	 * 
	 * @param id
	 *            the id of the followed thing
	 * @param type
	 *            the type of the followed thing
	 * @param followed
	 *            follow/unfollow
	 */
	public static void setFollows(long id, String type, boolean followed) {
		Application.unfollowOrganization(id);
		JsonObject result = new JsonObject();
		result.addProperty("done", "done");
		renderJSON(result.toString());
	}

	/**
	 * renders the friends to be put in the friend list
	 */
	public static void getFriends() {
		IdeaDeveloper ideaDeveloper = IdeaDeveloper.findById(Security.userid());

		// ideaDeveloper.friends;
		JsonObject friends = new JsonObject();
		try {
			if (ideaDeveloper.friends.size() == 0) {
				friends.addProperty("friends", "you have no friends currently!");
			} else {
				String allFriends = "<ul>";
				for (int i = 0; i < ideaDeveloper.friends.size(); i++) {
					allFriends += "<li><a href=\"http://localhost:9000/userprofile/otheruserprofile?userId="
							+ ideaDeveloper.friends.get(i).id
							+ "\"><img src=\"../../../public/images/chat-thumb.gif\" alt=\"\" />"
							+ ideaDeveloper.friends.get(i).username
							+ "</a></li>";
				}
				allFriends += "</ul>";
				friends.addProperty("friends", allFriends);
			}
		} catch (Exception e) {
			friends.addProperty("friends", "you have no friends currently!");
		}
		renderJSON(friends.toString());
	}

	/**
	 *  checks if the logged in user is a system admin and renders
	 * the result to the view
	 */
	public static void isAdmin() {
		JsonObject isAdmin = new JsonObject();
		boolean flag = Security.connected().equals("administrator");
		isAdmin.addProperty("admin", flag);
		renderJSON(isAdmin.toString());
	}

	/**
	 * Checks if the username is available in the data base, not a friend to the
	 * connected user and he is not the user himself and renders the result to
	 * the view
	 * 
	 * @param username
	 *            the username which will be checked
	 */
	public static void isAvailable(String username) {
		JsonObject usernameValid = new JsonObject();
		boolean flag = false;
		IdeaDeveloper connected = IdeaDeveloper.find("username=?",
				Security.connected()).first();
		if (IdeaDeveloper.find("username=?", username).fetch().size() > 0) {
			if (!connected.friends.contains(IdeaDeveloper.find("username=?",
					username).first())) {
				if (!Security.connected().equals(username)) {
					if (Request.count("dev=? and inviterName=? and type=?",
							IdeaDeveloper.find("username=?", username).first(),
							Security.connected(), "FriendRequest") == 0) {
						flag = true;
					} else {
						usernameValid.addProperty("error",
								"You have invited that user before!");
					}
				} else {
					usernameValid.addProperty("error",
							"You cannot invite yourself!");
				}
			} else {
				usernameValid.addProperty("error", "You are already friends!");
			}
		} else {
			usernameValid.addProperty("error", "Invalid username!");
		}
		usernameValid.addProperty("valid", flag);
		renderJSON(usernameValid.toString());
	}

	/**
	 *  sends a friend request to a given user
	 * 
	 * @param username
	 *            the user name of the person that is invited
	 */
	public static void inviteToBeFriend(String username) {
		IdeaDeveloper invited = IdeaDeveloper.find("username=?", username)
				.first();
		JsonObject requestSent = new JsonObject();
		requestSent.addProperty("sent", true);
		Request.RequestMe(Security.connected(), invited);
		renderJSON(requestSent.toString());
	}

	/**
	 * check if a user with this username is present in the system or not
	 * 
	 * @param username
	 *            the user name which will be checked
	 */
	public static void usernameValid(String username) {
		JsonObject check = new JsonObject();
		try {
			IdeaDeveloper ideaDeveloper = IdeaDeveloper.find("username=?",
					username).first();
			check.addProperty("res", true);
		} catch (Exception e) {
			check.addProperty("res", false);
		}
		renderJSON(check.toString());
	}
}